Module:Common

From Dune: Awakening Community Wiki
Jump to navigation Jump to search

Module:Common

Shared stateless helper functions, which can be loaded in other Lua modules via:

local common = require("Module:Common")

Usage

This module also exposes a few permanent utility entry points.

Get URL-safe version of a given string

MessageBundle keys are built from a slugified (URL-safe) version of a string. Use this to check the exact slug a given input will produce.

If no value is specified, it defaults to the current page's title:

{{#invoke:Common|checkSlug}}

A specific string can also be provided instead:

{{#invoke:Common|checkSlug|Terrarium of Muad'Dib}}

Get an auto-localised string from a MessageBundle

Retrieves a string for a given key from a specified MessageBundle. It auto-switches to the language that the viewer's page is currently on, and falls back to the English source if no translation exists for the current language.

{{#invoke:Common|localise|Vehicles|sandbike-name}}

Optionally, set link=yes to wrap the result as a stable link to the English page name, e.g. [[Wildlife of Arrakis|Fauna von Arrakis]]:

{{#invoke:Common|localise|DLC|wildlife-of-arrakis-name|link=yes}}

Parameters

checkSlug

1 (optional)
string
The string to generate a slug for.
If omitted, defaults to the current page's title.

localise

1
string
The name of the MessageBundle to look up (without the "MessageBundle:" prefix).
2
string
The key to retrieve from the MessageBundle.
link (optional)
boolean
If true, wraps the result as [[English|Translation]] instead of just plain text.
Defaults to false.

local p = {}

local tmb = require("mw.ext.translate.messageBundle")

-- ---------- String ----------

-- trims any whitespace on the edges
function p.trim(s)
    return mw.text.trim(s or "")
end

-- converts string to lowercase and trims any whitespace on the edges
function p.lowerTrim(s)
    return mw.ustring.lower(p.trim(s))
end

-- checks whether a string represents a truthy value; case-insensitive
function p.isTruthy(s)
    s = p.lowerTrim(s)
    return s == "true" or s == "yes" or s == "1"
end

-- checks whether a list of strings contains a specified token; case-insensitive
function p.listContains(list, token)
    token = p.lowerTrim(token)

    for _, item in ipairs(list) do
        if p.lowerTrim(item) == token then return true end
    end
    return false
end

-- splits a "Bundle:slug" source token into its parts
function p.parseSourceToken(token)
    return token:match("^([^:]+):(.+)$")
end

-- returns a URL-friendly version of a specified string
function p.slugify(name)
    local s = mw.text.decode(name)
    s = mw.ustring.lower(s)
    s = mw.ustring.gsub(s, "[^%w%s_]", "")
    s = mw.ustring.gsub(s, "%s+", "_")
    s = mw.ustring.gsub(s, "_+", "_")
    s = mw.ustring.gsub(s, "^_+", ""):gsub("_+$", "")
    return s
end

-- returns a display-ready error message, standardised for use across all modules
-- any number of extra args can be specified to be encoded and substituted into msg
function p.error(msg, ...)
    if select("#", ...) > 0 then
        local args = {...}
        for i = 1, #args do args[i] = mw.text.encode(tostring(args[i])) end
        msg = string.format(msg, unpack(args))
    end

    return '<strong class="error">⚠ ' .. msg .. '</strong>'
end

-- ---------- Translation ----------

-- retrieves a string value associated with a specified key from a specified MessageBundle
-- optionally wraps the result as [[<ENGLISH>|<TRANSLATION>]] if `link` is true
function p.translate(bundleName, key, lang, link, silent)
    local bundlePage = "MessageBundle:" .. bundleName
    
    -- if `lang` is nil, tmb.new() automatically attempts to grab a string of the invoking page's language
    -- if a translation does not exist, it falls back to the English source
    local ok, mb = pcall(tmb.new, bundlePage, lang)

    if not ok then
        if silent then return nil end
        return p.error("MessageBundle:%s not found.", bundleName)
    end

    local msg = mb:t(key)

    if not msg then
        if silent then return nil end
        return p.error("Missing key '%s' in MessageBundle:%s.", key, bundleName)
    end

    local translated = msg:plain()
    if not link then return translated end

    local _, mbEn = pcall(tmb.new, bundlePage, "en")

    return string.format("[[%s|%s]]", mbEn:t(key):plain(), translated)
end

-- ---------- Rendering ----------

-- creates a standard sortable, collapsible wikitable with a count-prefixed caption
-- returns the mw.html table object, ready for header/rows to be added
function p.newSortableTable(count, bundleName, labelKey)
    local table_ = mw.html.create("table")
        :addClass("wikitable sortable mw-collapsible")
        :css("text-align", "center")

    table_:tag("caption"):addClass("scalable-text")
        :wikitext(string.format("%dx %s&nbsp;", count, p.translate(bundleName, labelKey, nil, true)))

    return table_
end

-- ---------- Interface ----------

-- wrapper for p.slugify(), exposed as an entry point to check URL-friendly versions of specified strings
-- this is specifically intended to help in cases where it may not be clear what IDs to use in MessageBundles
function p.checkSlug(frame)
    local input = frame.args[1]
    if not input or input == "" then input = mw.title.getCurrentTitle().rootText end
    return p.slugify(input)
end

-- wrapper for p.translate(), exposed as an entry point for wikitext pages to grab strings from MessageBundles directly
function p.localise(frame)
    local args = frame.args
    return p.translate(args[1], args[2], nil, p.isTruthy(args.link))
end

return p