制作根据参数显示不同内容的 Mediawiki 模板的最佳方法?

Best way to make Mediawiki template which displays different content depending on parameter?

我会有数百个人物传记,其中包含一些文本、标记和图像。

我想要一个模板,您可以在其中编写例如{{Biography|Steven}} 它从所有 bios 的页面中抓取该传记,其中每个 bios 都链接到一个参数。

此外,可以选择只显示个人简介的一部分,例如{{传记|史蒂文|个性}}

我知道我可以为每本传记制作一个模板,但是我会有数百个模板,编辑必须找到这些模板,而且我不知道这是否是好的性能明智的(可以吗?)。

那我还是不知道怎么设置模板有条件地显示在bio的某些部分。

我也想知道我是否应该有一些数据存储扩展,但我不明白这可能比嵌入页面上的文本更快。

我是否需要使用 ParserFunctions 或我的偏好 Lua 的条件代码,并使用 its many possible versions of a switch statement.

我认为这个模板是一个很好的功能,因为人们可以在一页上编辑任何个人简介,或者在一页上为每个字符分类编辑,然后任何人都可以嵌入它,而不是写出相同的内容但出错,浪费时间等

此模板的使用率非常高,因此它的性能良好且易于编辑使用非常重要。

我不是要别人帮我写,只是建议如何去做。

为此,您需要使数据 granular 足以 select 个人传记字段。在 MediaWiki 中有几种方法可以做到这一点。

解析器函数

您可以使用 #switch 语句创建一个模板来完成这项工作,而无需添加任何扩展。例如,您可以在 Template:Biography/data:

有一个数据模块
{{#switch: {{{character|}}}
| Steven = {{#switch: {{{trait|}}}
  | Personality = Outgoing
  | Age = 25
  }}
| Dennis = {{#switch: {{{trait|}}}
  | Personality = Shy
  | Age = 34
  }}
}}

然后您可以像这样从 Template:Biography 调用它:

{{#if: {{{2|}}}
 | {{Biography/data|character={{{1|}}}|trait={{{2|}}}}}
 |
* Name: {{{1|}}}
* Age: {{Biography/data|character={{{1|}}}|trait=Age}}
* Personality: {{Biography/data|character={{{1|}}}|trait=Personality}}
 }}

您可以用几种不同的方式组织这个#switch 语句。例如,您可以将每个字符的数据存储在 Template:Biography 的不同子模板中,例如 Template:Biography/data/StevenTemplate:Biography/data/Dennis

模板:传记:

{{#if: {{{2|}}}
 | {{Biography/data|{{{1|}}}|{{{2|}}}}}
 |
* Name: {{{1|}}}
* Age: {{Biography/data|{{{1|}}}|Age}}
* Personality: {{Biography/data|{{{1|}}}|Personality}}
 }}

模板:Biography/data

{{Biography/data/{{{1|}}}|trait={{{2|}}}}}

模板:Biography/data/史蒂文:

{{#switch: {{{trait|}}}
| Personality = Outgoing
| Age = 25
}}

这比我们的第一次尝试要好,因为长 switch 语句在 MediaWiki 中是出了名的慢。但是,您仍然需要两级子模板才能使其工作,如果您不指定特征,则必须多次调用子模板。所以它仍然会很慢。

Scribunto

您可以通过 Scribunto 扩展在 Lua 中编写模板来加快速度。你可以这样写一个数据模块(假设它被称为Module:Biography/data):

return {
    ['Steven'] = {
        Personality = 'Outgoing',
        Age = 25,
    },
    ['Dennis'] = {
        Personality = 'Shy',
        Age = 34,
    },
}

然后您可以使用 mw.loadData 加载数据,这将在每页加载一次整个 table,而不是每次使用 {{Biography}} 模板时。例如:

local data = mw.loadData('Module:Biography/data')
local p = {}

local BIO_TEMPLATE = [[
* Name: %s
* Age: %d
* Personality: %s]]

-- Trim whitespace from args, and treat blank args as nil
local function preprocessArg(s)
    if not s then
        return nil
    end
    s = s:match('^%s*(.-)%s*$') -- trim whitespace
    if s == '' then
        return nil
    else
        return s
    end
end

function p.main(frame)
    local args = frame.args
    local character = preprocessArg(args[1])
    local trait = preprocessArg(args[2])

    -- Check for blank character arguments
    if not character then
        return ''
    end

    -- Get the data for the specified character
    local characterData = data[character]
    if not characterData then
        return ''
    end

    if trait then
        -- User specified a trait, so return it
        return characterData[trait] or ''
    else
        -- Return the biography template with all the traits in it
        return string.format(
            BIO_TEMPLATE,
            character,
            characterData.Age,
            characterData.Personality
        )
    end
end

return p

您还可以按字符或特征拆分数据页,与使用 #switch 的方式大致相同。

使用 Lua 的缺点是您的编辑需要学习 Lua 语法以及 wikitext 语法才能将条目添加到数据模块。 Lua 语法通常比 wikitext 更难掌握,所以这可能会阻止人们做出贡献。

扩展程序

wikitext 数据非结构化的问题是一个长期存在的问题,因此多年来已经进行了很多尝试来修复它。在选择纯解析器函数或纯 Scribunto 之前,您最好研究一下为尝试解决此问题而进行的一些扩展。 (请记住,您可以通过模板访问这些扩展,通常也可以通过 Scribunto。)

例如,labeled section transclusion 扩展允许您为您的角色写一个普通的传记,分隔不同的部分,然后将这些部分单独嵌入到其他页面。

还有更多以数据为中心的扩展,可以帮助您制作更精细的模板,而不会陷入切换功能或数据模块的泥潭:

这些会将您的数据字段单独存储在数据库中(通常与您安装的 MediaWiki 相同),因此性能特征将取决于您需要多少次数据库访问才能生成一个页面,以及您如何设置缓存向上。

如果我是你,我会先看看可用的扩展,看看是否有适合你情况的东西,然后使用模板或 Scribunto 对其进行微调。