理想情况下,在通过主题/插件定制 Discourse 时,应使用 CSS、JavaScript 插件 API 或 插件出口(Plugin Outlets)。如果这些方法都不适用于您的使用场景,请随时向 Discourse 核心提交 PR,或在此处的 Meta 上发起一个 Development 主题。我们总是乐于讨论添加新的出口/API,以使定制变得更加容易。
如果您已经穷尽了所有其他选择,可能需要诉诸于模板覆盖(template overrides)。这种技术允许您从您的主题/插件中覆盖任何 Ember 组件或路由的整个模板。
这不是定制 Discourse 的推荐方式。 Discourse 核心中的日常变更最终会与您的模板覆盖发生冲突,可能会导致渲染论坛时出现灾难性的错误。
如果您决定采用这种方法,请确保您拥有足够的自动化测试和 QA 流程来检测回归问题。如果您分发的主题/插件包含模板覆盖,请确保论坛管理员了解您的主题/插件所携带的稳定性风险。
![]()
![]()
2023 年 10 月更新:对于新功能,Discourse 正越来越多地转向使用 Ember 的
.gjs文件格式编写的组件。这些组件的模板是内联定义的,无法通过主题/插件进行覆盖。今后,所有模板定制都应使用 Plugin Outlets 来完成。
我知道这很快会失效,但还是给我看文档
覆盖组件模板
要覆盖 Ember 组件的模板(即 Discourse 核心中 components/* 下的任何内容),您应该在您的主题/插件中创建一个同名 .hbs 文件。例如,要覆盖 Discourse 核心中 badge-button 组件的模板,您需要在主题/插件中的以下位置创建一个模板文件:
{theme}/javascripts/discourse/templates/components/badge-button.hbs
{plugin}/assets/javascripts/discourse/templates/components/badge-button.hbs
即使核心组件具有“共置”(colocated)模板,覆盖文件也必须始终嵌套在 /templates 目录内。
覆盖路由模板
覆盖路由模板(即 templates/* 下的所有非组件模板)的方式与组件相同。在您的主题/插件中创建一个同名模板。例如,要覆盖核心中的 discovery.hbs,您需要创建一个如下所示的文件:
{theme}/javascripts/discourse/templates/discovery.hbs
{plugin}/assets/javascripts/discourse/templates/discovery.hbs
多个主题/插件之间的交互
如果多个已安装的主题/插件覆盖了同一个模板,“获胜者”是以下列表中排名编号最低的那个:
- 主题覆盖(具有最高主题 ‘id’ 的主题获胜)
- 插件覆盖(字母顺序最新的插件名称获胜)
- 核心
这种优先级还意味着您可以从主题中覆盖插件模板。从技术上讲,您也可以从其他主题中覆盖主题模板,从其他插件中覆盖插件模板,但由于依赖于插件名称和主题 ID,其行为可能会令人惊讶。
这是如何工作的?
Discourse 在 DiscourseTemplateMap 类中组装并优先处理模板。对于共置的组件模板,该信息在 应用程序初始化期间 用于替换核心模板关联。对于所有其他模板,该映射由 运行时解析器 用于获取正确的模板。
本文档受版本控制 - 请在 github 上建议更改。